package com.itaming.lycheeframework.security.exception;

import com.itaming.lycheeframework.api.exception.ExceptionDescriptor;
import com.itaming.lycheeframework.api.exception.ExceptionResolver;
import org.springframework.http.HttpStatus;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Security模块异常解析器
 *
 * @author A.Ming
 */
public class SecurityExceptionResolver implements ExceptionResolver {

    /**
     * http状态码映射
     */
    private static final Map<Class<?>, HttpStatus> STATUS_MAP = Map.of(
        AuthenticationException.class, HttpStatus.UNAUTHORIZED,
        AccessDeniedException.class, HttpStatus.FORBIDDEN
    );

    /**
     * http状态码映射缓存
     */
    private static final Map<Class<?>, HttpStatus> STATUS_MAP_CACHE = new ConcurrentHashMap<>();

    /**
     * 是否支持处理
     *
     * @param aClass 异常类
     * @return boolean
     */
    @Override
    public boolean supports(Class<?> aClass) {
        return SecurityException.class.isAssignableFrom(aClass);
    }

    /**
     * 处理异常
     *
     * @param exception 异常
     * @return 异常描述
     */
    @Override
    public ExceptionDescriptor resolve(Exception exception) {
        // 转为SecurityException
        SecurityException e = (SecurityException) exception;
        // 获取http状态码
        HttpStatus httpStatus = STATUS_MAP_CACHE.computeIfAbsent(e.getClass(), this::findHttpStatus);

        // 封装并返回异常信息
        return ExceptionDescriptor.builder()
            .httpStatus(httpStatus)
            .code(e.getCode())
            .message(e.getMessage())
            .build();
    }

    /**
     * 查找http状态码
     *
     * @param aClass 异常类
     * @return http状态码
     */
    private HttpStatus findHttpStatus(Class<?> aClass) {
        for (Map.Entry<Class<?>, HttpStatus> entry : STATUS_MAP.entrySet()) {
            if (entry.getKey().isAssignableFrom(aClass)) {
                return entry.getValue();
            }
        }

        return null;
    }

}
